﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Arroguella.Utilities;
using Arroguella.Entities;

namespace Arroguella.Panels.Popups
{
    public class CharacterSheet : ScreenPanel
    {
        #region Constructor

        public CharacterSheet(Player player, Rectangle rectangle, Game game) : base(game)
        {
            Player = player;
            SetSizeAndShape(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
            HeaderRect = new Rectangle(SizeAndShape.X, SizeAndShape.Y, SizeAndShape.Width, 30);
            InitializeElements();
        }

        #endregion

        #region Methods

        #region Initialization

        private void InitializeElements()
        {
            InitializeStats();
            InitializeSkills();
            InitializeEquipment();
        }

        private void InitializeStats()
        {
            Stats = new List<KeyValuePair<string, Color>>();

            AddElement("PLAYER STATS", STATS_COLOR, Stats);

            AddElement("--", Color.Gray, Stats);

            string lvl = string.Format("Character Level: {0}", Player.Level);
            AddElement(lvl, STATS_COLOR, Stats);

            string xp = string.Format("XP: {0} / {1}", Player.XP, Player.XpForNextLevel);
            AddElement(xp, STATS_COLOR, Stats);

            string hp = string.Format("HP: {0} / {1}", Player.CurrentHealth, Player.MaxHealth);
            AddElement(hp, STATS_COLOR, Stats);

            string mana = string.Format("Mana: {0} / {1}", Player.CurrentMana, Player.MaxMana);
            AddElement(mana, STATS_COLOR, Stats);            

            string str = string.Format("STR {0}", Player.Strength);
            AddElement(str, STATS_COLOR, Stats);

            string agi = string.Format("AGI {0}", Player.Agility);
            AddElement(agi, STATS_COLOR, Stats);

            string sInt = string.Format("INT {0}", Player.Intelligence);
            AddElement(sInt, STATS_COLOR, Stats);

            string defense = string.Format("DEFENSE {0}", Player.Defense);
            AddElement(defense, STATS_COLOR, Stats);
            
            // Money
            string money;
            float amount = Player.Money;
            if (amount < 0.10)
            {
                money = string.Format("Money: {0}", Player.GetProperty("CP"));
                AddElement(money, Color.DarkOrange, Stats);
            }
            else if (amount >= 0.10 && amount < 1.00)
            {
                money = string.Format("Money: {0}", Player.GetProperty("SP"));
                AddElement(money, Color.LightSlateGray, Stats);
            }
            else if (amount >= 1.00)
            {
                money = string.Format("Money: {0}", Player.GetProperty("GP"));
                AddElement(money, Color.Goldenrod, Stats);
            }
        }

        private void InitializeSkills()
        {
            Skills = new List<KeyValuePair<string, Color>>();

            AddElement("SKILLS", SKILLS_COLOR, Skills);

            AddElement("--", Color.Gray, Skills);

            // Skills
            foreach (KeyValuePair<string, float> skill in Player.Skills)
            {
                string s = string.Format("{0}: {1}", skill.Key, skill.Value);
                AddElement(s, SKILLS_COLOR, Skills);
            }
        }

        private void InitializeEquipment()
        {
            Equipment = new List<KeyValuePair<string, Color>>();

            AddElement("EQUIPMENT", EQUIPMENT_COLOR, Equipment);

            AddElement("--", Color.Gray, Equipment);

            // Equipment
            foreach (KeyValuePair<string, Entity> equipment in Player.EquipmentSlots)
            {
                string slot = equipment.Key;
                string item = equipment.Value.Name;
                string equippedSlot = string.Format("{0}: {1}", slot, item);
                AddElement(equippedSlot, EQUIPMENT_COLOR, Equipment);
            }
        }

        #endregion

        #region Drawing

        public override void Draw(SpriteBatch spriteBatch)
        {
            DrawBackground(spriteBatch);
            DrawHeader(spriteBatch);
            DrawElements(spriteBatch);
        }

        private void DrawBackground(SpriteBatch spriteBatch)
        {
            Utils.DrawFilledRectangle(Color.FromNonPremultiplied(80, 80, 80, 210), SizeAndShape, spriteBatch, base.Arroguella.GraphicsDevice);
            Utils.DrawRectangleBorder(SizeAndShape, 6, Color.Gray, spriteBatch, base.Arroguella.GraphicsDevice);
        }

        private void DrawHeader(SpriteBatch spriteBatch)
        {
            // Header Box
            Utils.DrawFilledRectangle(Color.Gray, HeaderRect, spriteBatch, Arroguella.GraphicsDevice);

            // Title
            Utils.DrawString(spriteBatch, base.Font, "Character Sheet", Color.White, HeaderRect);
        }

        private void DrawElements(SpriteBatch spriteBatch)
        {
            DrawStats(spriteBatch);
            DrawSkills(spriteBatch);
            DrawEquipment(spriteBatch);
        }

        private void DrawStats(SpriteBatch spriteBatch)
        {
            Rectangle elementRect = new Rectangle(SizeAndShape.X + 10, SizeAndShape.Y + 40, ELEMENT_WIDTH / 5, ELEMENT_HEIGHT);
            foreach (KeyValuePair<string, Color> element in Stats)
            {
                // Special case, convert any instance of multiple dashes to a line
                if (element.Key.Contains("--"))
                {
                    Rectangle line = new Rectangle(elementRect.X, elementRect.Y + (elementRect.Height / 2), (ELEMENT_WIDTH / 5) - 6, 1);
                    Utils.DrawFilledRectangle(element.Value, line, spriteBatch, Arroguella.GraphicsDevice);
                }
                else
                {
                    Utils.DrawStringWrappedInRectangle(element.Key, elementRect, element.Value, PlayerInfoFont, spriteBatch);
                }

                elementRect.Y += ELEMENT_HEIGHT + 3;
            }
        }

        private void DrawSkills(SpriteBatch spriteBatch)
        {
            Rectangle elementRect = new Rectangle(SizeAndShape.X + 10 + ELEMENT_WIDTH / 5 + 10, SizeAndShape.Y + 40, ELEMENT_WIDTH / 5, ELEMENT_HEIGHT);
            foreach (KeyValuePair<string, Color> element in Skills)
            {
                // Special case, convert any instance of multiple dashes to a line
                if (element.Key.Contains("--"))
                {
                    Rectangle line = new Rectangle(elementRect.X, elementRect.Y + (elementRect.Height / 2), (ELEMENT_WIDTH / 5) - 6, 1);
                    Utils.DrawFilledRectangle(element.Value, line, spriteBatch, Arroguella.GraphicsDevice);
                }
                else
                {
                    Utils.DrawStringWrappedInRectangle(element.Key, elementRect, element.Value, PlayerInfoFont, spriteBatch);
                }

                elementRect.Y += ELEMENT_HEIGHT + 3;
            }
        }

        private void DrawEquipment(SpriteBatch spriteBatch)
        {
            Rectangle elementRect = new Rectangle(SizeAndShape.X + 10 + (2 * ELEMENT_WIDTH / 5) + 20, SizeAndShape.Y + 40, ELEMENT_WIDTH / 5, ELEMENT_HEIGHT);
            foreach (KeyValuePair<string, Color> element in Equipment)
            {
                // Special case, convert any instance of multiple dashes to a line
                if (element.Key.Contains("--"))
                {
                    Rectangle line = new Rectangle(elementRect.X, elementRect.Y + (elementRect.Height / 2), (ELEMENT_WIDTH / 5) - 6, 1);
                    Utils.DrawFilledRectangle(element.Value, line, spriteBatch, Arroguella.GraphicsDevice);
                }
                else
                {
                    Utils.DrawStringWrappedInRectangle(element.Key, elementRect, element.Value, PlayerInfoFont, spriteBatch);
                }

                elementRect.Y += ELEMENT_HEIGHT + 3;
            }
        }

        #endregion

        private void AddElement(string text, Color color, List<KeyValuePair<string, Color>> elements)
        {
            elements.Add(new KeyValuePair<string, Color>(text, color));
        }

        #endregion

        #region Properties

        protected Player Player { get; set; }

        protected List<KeyValuePair<string, Color>> Stats;
        protected List<KeyValuePair<string, Color>> Skills;
        protected List<KeyValuePair<string, Color>> Equipment;

        private Color ELEMENTS_COLOR = Color.Gainsboro;
        private Color STATS_COLOR = Color.DarkGray;
        private Color SKILLS_COLOR = Color.SeaGreen;
        private Color EQUIPMENT_COLOR = Color.LightSeaGreen;

        private new SpriteFont Font { get {return base.Arroguella.PlayerInfoFont; } }

        private Rectangle HeaderRect;

        private int ELEMENT_WIDTH { get { return SizeAndShape.Width; } }
        private const int ELEMENT_HEIGHT = 15;
        private const int ELEMENT_SPACING = 10;

        #endregion
    }
}
